/**
 * 
 */
package co.fitstart.admin.dao;

import java.util.Date;
import java.util.List;

import com.demo2do.core.persistence.annotation.Dynamic;
import com.demo2do.core.persistence.annotation.Execute;
import com.demo2do.core.persistence.annotation.Limit;
import com.demo2do.core.persistence.annotation.Query;
import com.demo2do.core.persistence.annotation.Variable;

import co.fitstart.entity.course.round.OnlineRoundGroupStatus;
import co.fitstart.entity.course.round.RoundStatus;
import co.fitstart.entity.finance.InvoiceExportRecord;
import co.fitstart.entity.finance.OrderInvoiceRecord;
import co.fitstart.entity.finance.PaidType;
import co.fitstart.entity.finance.Receipt;
import co.fitstart.entity.finance.ReceiptExportRecord;
import co.fitstart.entity.finance.SalesOrderExportRecord;
import co.fitstart.entity.order.Order;
import co.fitstart.entity.order.OrderAttribute;
import co.fitstart.entity.order.OrderInvestigateRecord;
import co.fitstart.entity.order.OrderStatus;
import co.fitstart.entity.order.OrderType;
import co.fitstart.entity.order.PaymentStatus;
import co.fitstart.entity.product.Product;
import co.fitstart.entity.site.Site;
import co.fitstart.entity.user.User;
import co.fitstart.entity.user.agent.Agent;

/**
 * @author downpour
 *
 */
@Dynamic("hibernate")
public interface OrderDao {
    
    /**
     * list order by orderType, orderStatus and page
     * 
     * @param orderType
     * @param status
     * @param beginIndex
     * @param maxResult
     * @return
     */
    @Limit
    @Query("FROM Order order WHERE order.disabled = false AND order.orderType = :orderType AND order.orderStatus in(:status) ORDER BY order.payTime DESC, order.createTime DESC")
    public List<Order> listByPage(@Variable("orderType")OrderType orderType, @Variable("status")List<OrderStatus> status, @Variable("beginIndex") int beginIndex, @Variable("maxResult") int maxResult);
    
    /**
     * list order by orderType, experience, orderStatus and page
     * @param orderType
     * @param experience
     * @param status
     * @param beginIndex
     * @param maxResult
     * @return
     */
    @Limit
    @Query("FROM Order order WHERE order.disabled = false AND order.orderType = :orderType AND order.course.experience = :experience AND order.course.give = :give AND order.orderStatus in(:status) ORDER BY order.payTime DESC, order.createTime DESC")
    public List<Order> listByPage(@Variable("orderType")OrderType orderType, @Variable("experience")boolean experience, @Variable("give")boolean give, @Variable("status")List<OrderStatus> status, @Variable("beginIndex") int beginIndex, @Variable("maxResult") int maxResult);
    
    /**
     * list order by site, orderType, course and page
     * 
     * @param site
     * @param orderType
     * @param status 
     * @param beginIndex
     * @param maxResult
     * @return
     */
    @Limit
    @Query("FROM Order order WHERE order.disabled = false AND order.orderType = :orderType AND order.site = :site AND order.orderStatus in(:status) ORDER BY order.payTime DESC, order.createTime DESC")
    public List<Order> listByPage(@Variable("site")Site site, @Variable("orderType")OrderType orderType, @Variable("status")List<OrderStatus> status, @Variable("beginIndex") int beginIndex, @Variable("maxResult") int maxResult);
    
    /**
     * 
     * @param sites
     * @param orderType
     * @param status
     * @param beginIndex
     * @param maxResult
     * @return
     */
    @Limit
    @Query("FROM Order order WHERE order.disabled = false AND order.orderType = :orderType AND order.site IN (:sites) AND order.orderStatus in(:status) ORDER BY order.payTime DESC, order.createTime DESC")
    public List<Order> listByPage(@Variable("sites")List<Site> sites, @Variable("orderType")OrderType orderType, @Variable("status")List<OrderStatus> status, @Variable("beginIndex") int beginIndex, @Variable("maxResult") int maxResult);
    
    /**
     * list order by site, orderType, experience, status and page
     * @param site
     * @param orderType
     * @param experience
     * @param status
     * @param beginIndex
     * @param maxResult
     * @return
     */
    @Limit
    @Query("FROM Order order WHERE order.disabled = false AND order.orderType = :orderType AND order.course.experience = :experience AND order.course.give = :give AND order.site = :site AND order.orderStatus in(:status) ORDER BY order.payTime DESC, order.createTime DESC")
    public List<Order> listByPage(@Variable("site")Site site, @Variable("orderType")OrderType orderType, @Variable("experience")boolean experience, @Variable("give")boolean give, @Variable("status")List<OrderStatus> status, @Variable("beginIndex") int beginIndex, @Variable("maxResult") int maxResult);
    
    /**
     * 
     * @param sites
     * @param orderType
     * @param experience
     * @param status
     * @param beginIndex
     * @param maxResult
     * @return
     */
    @Limit
    @Query("FROM Order order WHERE order.disabled = false AND order.orderType = :orderType AND order.course.experience = :experience AND order.course.give = :give AND order.site IN (:sites) AND order.orderStatus in(:status) ORDER BY order.payTime DESC, order.createTime DESC")
    public List<Order> listByPage(@Variable("sites")List<Site> sites, @Variable("orderType")OrderType orderType, @Variable("experience")boolean experience, @Variable("give")boolean give, @Variable("status")List<OrderStatus> status, @Variable("beginIndex") int beginIndex, @Variable("maxResult") int maxResult);
    
    /**
     * 
     * @param site
     * @param orderType
     * @param beginIndex
     * @param maxResult
     * @return
     */
    @Limit
    @Query("FROM Order order WHERE order.disabled = false AND order.orderType = :orderType AND order.site = :site ORDER BY order.createTime DESC, order.payTime DESC")
    public List<Order> listByPage(@Variable("site")Site site, @Variable("orderType")OrderType orderType, @Variable("beginIndex") int beginIndex, @Variable("maxResult") int maxResult);
    
    /**
     * 
     * @param product
     * @param status
     * @return
     */
    @Query("FROM Order order WHERE disabled = false AND product = :product AND orderStatus in (:status)")
    public List<Order> list(@Variable("product") Product product, @Variable("status") List<OrderStatus> status);
    
    /**
     * 
     * @param groupStatus
     * @param code
     * @param status
     * @return
     */
    @Query("SELECT round.order FROM CourseRound round WHERE round.disabled = false AND round.onlineRoundAttr.onlineRoundGroupStatus in (:groupStatus) AND round.courseStatus = :status AND round.code = :code")
    public List<Order> listUnfinishOrder(@Variable("groupStatus") OnlineRoundGroupStatus[] groupStatus, @Variable("code") String code, @Variable("status") RoundStatus status);
    
    
    /**
     * @param orderType
     * @param agent
     * @param status
     * @return
     */
    @Query("FROM Order WHERE disabled = false AND orderType = :orderType AND agent IS NOT NULL AND agent = :agent AND paymentStatus = :status")
    public List<Order> list(@Variable("orderType") OrderType orderType, @Variable("agent") Agent agent, @Variable("status") PaymentStatus status);
    
    /**
     * 
     * @param roundIds
     * @return
     */
    @Query("SELECT round.order FROM CourseRound round WHERE round.disabled = false AND round.id in (:roundIds)")
    public List<Order> listOrder(@Variable("roundIds") List<Long> roundIds);
    
    /**
     * 
     * @param exportSale
     * @param payOffer
     * @param paymentStatus
     * @param date
     * @param beginIndex
     * @param maxResult
     * @return
     */
    @Limit
    @Query("FROM Order WHERE disabled = false AND exportSale = :exportSale AND payOffer = :payOffer AND paymentStatus in ( :paymentStatus ) AND course.group = false AND createTime >= :date")
    public List<Order> list(@Variable("exportSale") boolean exportSale, @Variable("payOffer") boolean payOffer, @Variable("paymentStatus") PaymentStatus[] paymentStatus, @Variable("date") Date date, @Variable("beginIndex") int beginIndex, @Variable("maxResult") int maxResult);
    
    
    /**
     * 
     * @param exportSale
     * @param paymentStatus
     * @param beginIndex
     * @param maxResult
     * @return
     */
    @Limit
    @Query("FROM Order WHERE disabled = false AND orderType != 4 AND exportReceipt = :exportReceipt AND paymentStatus in( :paymentStatus) AND createTime >= :date")
    public List<Order> list(@Variable("exportReceipt") boolean exportReceipt, @Variable("paymentStatus") PaymentStatus[] paymentStatus, @Variable("date") Date date, @Variable("beginIndex") int beginIndex, @Variable("maxResult") int maxResult);
    
    /**
     * 
     * @param payOffer
     * @param paymentStatus
     * @param date
     * @param city
     * @return
     */
    @Query("FROM Order WHERE disabled = false AND exportSale = false AND payOffer = :payOffer AND paymentStatus in ( :paymentStatus ) AND course.group = false AND createTime >= :date AND site.city = :city")
    public List<Order> list(@Variable("payOffer")boolean payOffer, @Variable("paymentStatus") PaymentStatus[] paymentStatus, @Variable("date") Date date, @Variable("city") String city);
    
    /**
     * 
     * @param paymentStatus
     * @param date
     * @return
     */
    @Query("FROM Order WHERE disabled = false AND orderType != 4 AND exportReceipt = false AND paymentStatus in (:paymentStatus) AND createTime >= :date")
    public List<Order> list(@Variable("paymentStatus") PaymentStatus[] paymentStatus, @Variable("date") Date date);
    
    /**
     * 
     * @param id
     * @param orderType
     * @param orderStatus
     * @param beginIndex
     * @param maxResult
     * @return
     */
    @Limit
    @Query("FROM Order WHERE disabled = false AND id = :id AND orderType = :orderType AND orderStatus = :orderStatus")
    public List<Order> list(@Variable("id") Long id, @Variable("orderType") OrderType orderType, @Variable("orderStatus") OrderStatus orderStatus, @Variable("beginIndex") int beginIndex, @Variable("maxResult") int maxResult);
    
    /**
     * 
     * @param id
     * @param orderType
     * @param experience
     * @param orderStatus
     * @param beginIndex
     * @param maxResult
     * @return
     */
    @Limit
    @Query("FROM Order WHERE disabled = false AND id = :id AND orderType = :orderType AND course.experience = :experience AND course.give = :give AND orderStatus = :orderStatus")
    public List<Order> list(@Variable("id") Long id, @Variable("orderType") OrderType orderType, @Variable("experience") boolean experience, @Variable("give") boolean give, @Variable("orderStatus") OrderStatus orderStatus, @Variable("beginIndex") int beginIndex, @Variable("maxResult") int maxResult);
    
    /**
     * 
     * @param orders
     * @return
     */
    @Query("FROM OrderInvestigateRecord WHERE order in (:orders)")
    public List<OrderInvestigateRecord> listOrderInvestigateRecord(@Variable("orders") List<Order> orders);
    
    /**
     * 
     * @param product
     * @param orderType
     * @param status
     * @return
     */
    @Query("FROM OrderInvestigateRecord WHERE order.disabled = false AND order.product = :product AND order.orderType = :orderType AND order.orderStatus in ( :status )")
    public List<OrderInvestigateRecord> getOrderInvestigateRecord(@Variable("product") Product product, @Variable("orderType") OrderType orderType, @Variable("status") List<OrderStatus> status);
    
    /**
     * 
     * @param order
     * @return
     */
    @Query("FROM OrderInvestigateRecord WHERE order = :order")
    public OrderInvestigateRecord loadOrderInvestigateRecord(@Variable("order")Order order);
    
    /**
     * 
     * @param order
     * @param name
     * @return
     */
    @Query("FROM OrderAttribute WHERE order = :order AND name = :name")
    public OrderAttribute getOrderAttribute(@Variable("order") Order order, @Variable("name") String name);
    
    /**
     * 
     * @param order
     * @return
     */
    @Query("FROM OrderInvoiceRecord WHERE order = :order")
    public OrderInvoiceRecord getOrderInvoiceRecord(@Variable("order") Order order);
    
    /**
     * 
     * @param ids
     */
    @Execute("UPDATE Order SET exportSale = true WHERE id in (:ids)")
    public void exportSales(@Variable("ids") List<Long> ids);
    
    /**
     * 
     * @param ids
     */
    @Execute("UPDATE Order SET exportReceipt = true WHERE id in (:ids)")
    public void exportReceipt(@Variable("ids") List<Long> ids);
    
    /**
     * 
     * @param beginIndex
     * @param maxResult
     * @return
     */
    @Limit
    @Query("FROM SalesOrderExportRecord ORDER BY createTime DESC")
    public List<SalesOrderExportRecord> listSaleExportRecord(@Variable("beginIndex") int beginIndex, @Variable("maxResult") int maxResult);

    /**
     * 
     * @param beginIndex
     * @param maxResult
     * @return
     */
    @Limit
    @Query("FROM ReceiptExportRecord ORDER BY type, createTime DESC")
    public List<ReceiptExportRecord> listReceiptExportRecord(@Variable("beginIndex") int beginIndex, @Variable("maxResult") int maxResult);
    
    /**
     * 
     * @param invoice
     * @param export
     * @param beginIndex
     * @param maxResult
     * @return
     */
    @Limit
    @Query("FROM OrderInvoiceRecord WHERE invoice = :invoice AND exportInvoice = :export AND createTime >= :date ORDER BY createTime DESC")
    public List<OrderInvoiceRecord> listOrderInvoiceRecord(@Variable("invoice") boolean invoice, @Variable("export") boolean export, @Variable("date") Date date, @Variable("beginIndex") int beginIndex, @Variable("maxResult") int maxResult);

    /**
     * 
     * @return
     */
    @Query("FROM OrderInvoiceRecord WHERE invoice = true AND exportInvoice = false AND createTime >= :date ORDER BY createTime DESC")
    public List<OrderInvoiceRecord> listOrderInvoiceRecord(@Variable("date") Date date);
    
    /**
     * 
     * @param ids
     */
    @Execute("UPDATE OrderInvoiceRecord SET exportInvoice = true WHERE id in (:ids)")
    public void exportOrderInvoiceRecord(@Variable("ids") List<Long> ids);
    
    /**
     * 
     * @param beginIndex
     * @param maxResult
     * @return
     */
    @Limit
    @Query("FROM InvoiceExportRecord ORDER BY createTime DESC")
    public List<InvoiceExportRecord> listInvoiceRecordExportRecord(@Variable("beginIndex") int beginIndex, @Variable("maxResult") int maxResult);
    
    /**
     * 
     * @param export
     * @param paidType
     * @param beginIndex
     * @param maxResult
     * @return
     */
    @Limit
    @Query("FROM Receipt WHERE export = :export AND paidType = :paidType AND createTime >= :date")
    public List<Receipt> listReceipt(@Variable("export") boolean export, @Variable("paidType") PaidType paidType, @Variable("date") Date date, @Variable("beginIndex") int beginIndex, @Variable("maxResult") int maxResult);

    /**
     * 
     * @param export
     * @return
     */
    @Query("FROM Receipt WHERE export = :export AND paidType = :paidType AND createTime >= :date")
    public List<Receipt> listReceipt(@Variable("export") boolean export, @Variable("paidType") PaidType paidType, @Variable("date") Date date);
    
    /**
     * 
     * @param ids
     */
    @Execute("UPDATE Receipt SET export = true WHERE id in (:ids)")
    public void exportSaleReceipt(@Variable("ids") List<Long> ids);
    
    /**
     * 
     * @param name
     * @param value
     * @return
     */
    @Query("SELECT order.id FROM OrderAttribute WHERE name = :name AND value = :value")
    public Long getOrderId(@Variable("name") String name, @Variable("value") String value);

    /**
     * 
     * @param user
     * @return
     */
    @Query("SELECT COUNT(*) FROM Order WHERE disabled = false AND user = :user")
    public int count(@Variable("user") User user);
}
